﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Common.Utilities.Excel.Validator
{
    public class ValidatorConfig
    {
        #region 属性

        public string Label {set;get;}
        public string Value {set; get;}
        public string Validator { set; get; }

        private ValidatorResult validatorResult = new ValidatorResult();

        #endregion

        #region 配置信息
        private const string KEY_VALUE_STRING = "value";
        private const string KEY_LABEL_STRING = "label";
        private const string KEY_VALIDATOR_STRING = "Validator";

        private const char RULE_SPILT_STRING = ',';
        private const string RULE_REQUIRED = "required";
        private const string RULE_PATTERN = "pattern";
        private const string RULE_LENGTH = "length";
        private const string RULE_RANGE = "range";
        private const string RULE_URL = "url";
        private const string RULE_QQ = "qq";
        private const string RULE_TELEPHONE = "telephone";
        private const string RULE_MOBILE = "mobile";
        private const string RULE_ZIP = "zip";
        private const string RULE_EMAIL = "email";
        private const string RULE_DATE = "date";
        private const string RULE_IDENTITY = "identity";
        private const string RULE_MONEY = "money";
        private const string RULE_INTEGER = "integer";
        private const string RULE_DOUBLE = "double";
        private const string RULE_DIGIT = "digit";
        private const string RULE_NOSPECIALCARACTERS = "nospecialcaracters";
        private const string RULE_LETTER = "letter";
        private const string RULE_CHINESE = "chinese";

        private const string MESSAGE_PATTERN = "pattern";
        private const string MESSAGE_LENGTH = "{0}输入值的长度必须在{1}和{2}之间";
        private const string MESSAGE_RANGE = "{0}输入值的范围必须在{1}和{2}之间";
        private const string MESSAGE_REQUIRED = "{0}为必填项";
        private const string MESSAGE_URL = "{0}为url";
        private const string MESSAGE_QQ = "{0}为qq";
        private const string MESSAGE_TELEPHONE = "{0}为telephone";
        private const string MESSAGE_MOBILE = "{0}为mobile";
        private const string MESSAGE_ZIP = "{0}为zip";
        private const string MESSAGE_EMAIL = "{0}为email";
        private const string MESSAGE_DATE = "{0}为date";
        private const string MESSAGE_IDENTITY = "{0}为identity";
        private const string MESSAGE_MONEY = "{0}为money";
        private const string MESSAGE_INTEGER = "{0}为integer";
        private const string MESSAGE_DOUBLE = "{0}为double";
        private const string MESSAGE_DIGIT = "{0}为digit";
        private const string MESSAGE_NOSPECIALCARACTERS = "{0}为nospecialcaracters";
        private const string MESSAGE_LETTER = "{0}为letter";
        private const string MESSAGE_CHINESE = "{0}为chinese";

        #endregion

        public ValidatorResult ValidatorData()
        {
            // 验证属性是否完整
            CheckFields();

            bool result = true;

            // 分解验证规则
            string[] validators = this.GetSpiltRules(Validator);
            foreach (string item in validators)
            {
                string val = item.Trim();

                // 长度
                if (val.StartsWith(RULE_LENGTH + "["))
                {
                    string min = this.GetMinValue(val);
                    string max = this.GetMaxValue(val);
                    try
                    {
                        result = this.IsBetweenLength(Value, min, max);
                        if (!result)
                        {
                            string message = this.GetErrorMessage(Label, RULE_LENGTH, min, max);
                            this.AddErrorMessage(message);
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        result = false;
                        this.AddErrorMessage(ex.Message);
                    }
                }
                // 范围
                else if (val.StartsWith(RULE_RANGE + "["))
                {
                    string min = this.GetMinValue(val);
                    string max = this.GetMaxValue(val);
                    try
                    {
                        result = this.IsBetweenRange(Value, min, max);
                        if (!result)
                        {
                            string message = this.GetErrorMessage(Label, RULE_RANGE, min, max);
                            this.AddErrorMessage(message);
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        result = false;
                        this.AddErrorMessage(ex.Message);
                    }
                }
                // 必填
                else if (val == RULE_REQUIRED)
                {
                    result = RegexUtil.IsRequried(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_REQUIRED);
                        this.AddErrorMessage(message);
                    }
                }
                // URL
                else if (val == RULE_URL)
                {
                    result = RegexUtil.IsUrl(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_URL);
                        this.AddErrorMessage(message);
                    }
                }
                // QQ
                else if (val == RULE_QQ)
                {
                    result = RegexUtil.IsQQ(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_QQ);
                        this.AddErrorMessage(message);
                    }
                }
                // 固定号码
                else if (val == RULE_TELEPHONE)
                {
                    result = RegexUtil.IsTelephone(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_TELEPHONE);
                        this.AddErrorMessage(message);
                    }
                }
                // 移动电话
                else if (val == RULE_MOBILE)
                {
                    result = RegexUtil.IsMobile(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_MOBILE);
                        this.AddErrorMessage(message);
                    }
                }
                // 邮编
                else if (val == RULE_ZIP)
                {
                    result = RegexUtil.IsZip(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_ZIP);
                        this.AddErrorMessage(message);
                    }
                }
                // 电子邮件
                else if (val == RULE_EMAIL)
                {
                    result = RegexUtil.IsEmail(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_EMAIL);
                        this.AddErrorMessage(message);
                    }
                }
                // 日期
                else if (val == RULE_DATE)
                {
                    result = RegexUtil.IsDate(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_DATE);
                        this.AddErrorMessage(message);
                    }
                }
                // 身份证
                else if (val == RULE_IDENTITY)
                {
                    result = RegexUtil.IsIdentity(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_IDENTITY);
                        this.AddErrorMessage(message);
                    }
                }
                // 金额
                else if (val == RULE_MONEY)
                {
                    result = RegexUtil.IsMoney(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_MONEY);
                        this.AddErrorMessage(message);
                    }
                }
                // 正整数
                else if (val == RULE_INTEGER)
                {
                    result = RegexUtil.IsInteger(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_INTEGER);
                        this.AddErrorMessage(message);
                    }
                }
                // 浮点数
                else if (val == RULE_DOUBLE)
                {
                    result = RegexUtil.isDouble(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_DOUBLE);
                        this.AddErrorMessage(message);
                    }
                }
                // 数字
                else if (val == RULE_DIGIT)
                {
                    result = RegexUtil.IsDigit(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_DIGIT);
                        this.AddErrorMessage(message);
                    }
                }
                // 数字+英文字母
                else if (val == RULE_NOSPECIALCARACTERS)
                {
                    result = RegexUtil.IsNoSpecialCaracters(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_NOSPECIALCARACTERS);
                        this.AddErrorMessage(message);
                    }
                }
                // 英文字母
                else if (val == RULE_LETTER)
                {
                    result = RegexUtil.IsLetter(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_LETTER);
                        this.AddErrorMessage(message);
                    }
                }
                // 汉字
                else if (val == RULE_CHINESE)
                {
                    result = RegexUtil.IsChinese(Value);
                    if (!result)
                    {
                        string message = this.GetErrorMessage(Label, RULE_CHINESE);
                        this.AddErrorMessage(message);
                    }
                }
                else
                {
                    // 异常
                    //throw Exception("验证类型\"{0}\"不存在");
                }
            }

            return this.validatorResult;
        }

        #region 私有方法

        private void CheckFields()
        {
            string message = "{0}属性不能为空";

            if (string.IsNullOrEmpty(Validator))
            {
                throw new Exception(string.Format(message, "Validator"));
            }

            if (string.IsNullOrEmpty(Label))
            {
                throw new Exception(string.Format(message, "Label"));
            }

            if (Value == null)
            {
                Value = "";
            }
        }

        private string[] GetSpiltRules(string validators)
        {
            IList<string> rtnList = new List<string>();

            string[] rules = validators.Split(RULE_SPILT_STRING);
            for (int i = 0; i < rules.Length; i++)
            {
                if (rules[i].Contains("["))
                {
                    rtnList.Add(rules[i] + RULE_SPILT_STRING + rules[i + 1]);
                    i++; // 跳过下一个
                }
                else
                {
                    rtnList.Add(rules[i]);
                }
            }

            // 构建返回数组
            string[] rtnArray = new string[rtnList.Count];
            for (int i = 0; i < rtnArray.Length; i++)
            {
                rtnArray[i] = rtnList[i];
            }
            return rtnArray;
        }

        private void AddErrorMessage(string message)
        {
            // 添加错误信息
            this.validatorResult.MessageList.Add(message);
            this.validatorResult.Result = false;
        }

        /// <summary>
        /// 根据验证类型获取错误信息
        /// </summary>
        /// <param name="label">验证信息名称</param>
        /// <param name="rule">验证类型</param>
        /// <returns></returns>
        private string GetErrorMessage(string label, string rule)
        {
            string message = "";
            switch (rule)
            {
                case RULE_REQUIRED: message = MESSAGE_REQUIRED; break;
                case RULE_URL: message = MESSAGE_URL; break;
                case RULE_QQ: message = MESSAGE_QQ; break;
                case RULE_TELEPHONE: message = MESSAGE_TELEPHONE; break;
                case RULE_MOBILE: message = MESSAGE_MOBILE; break;
                case RULE_ZIP: message = MESSAGE_ZIP; break;
                case RULE_EMAIL: message = MESSAGE_EMAIL; break;
                case RULE_DATE: message = MESSAGE_DATE; break;
                case RULE_IDENTITY: message = MESSAGE_IDENTITY; break;
                case RULE_MONEY: message = MESSAGE_MONEY; break;
                case RULE_INTEGER: message = MESSAGE_INTEGER; break;
                case RULE_DOUBLE: message = MESSAGE_DOUBLE; break;
                case RULE_DIGIT: message = MESSAGE_DIGIT; break;
                case RULE_NOSPECIALCARACTERS: message = MESSAGE_NOSPECIALCARACTERS; break;
                case RULE_LETTER: message = MESSAGE_LETTER; break;
                case RULE_CHINESE: message = MESSAGE_CHINESE; break;
                default: message = "验证类型{0}错误!"; break;
            }

            return String.Format(message, label);
        }

        /// <summary>
        /// 根据验证类型获取错误信息
        /// </summary>
        /// <param name="label">验证信息名称</param>
        /// <param name="rule">验证类型</param>
        /// <param name="min">最小值数字</param>
        /// <param name="max">最大值数字</param>
        /// <returns></returns>
        private string GetErrorMessage(string label, string rule, string min, string max)
        {
            string message = "";
            switch (rule)
            {
                case RULE_LENGTH: message = MESSAGE_LENGTH; break;
                case RULE_RANGE: message = MESSAGE_RANGE; break;
                default: message = "验证类型{0}错误!"; break;
            }

            return String.Format(message, label, min, max);
        }

        private string GetMaxValue(string val)
        {
            string[] values = GetBetweenContent(val);
            return values[1].Trim();
        }

        private string GetMinValue(string val)
        {
            string[] values = GetBetweenContent(val);
            return values[0].Trim();
        }

        private string[] GetBetweenContent(string val)
        {
            int startIndex = val.IndexOf('[');
            int endIndex = val.IndexOf(']');
            int dotIndex = val.IndexOf(',');

            if (startIndex == -1 || endIndex == -1 || dotIndex == -1)
            {
                // 长度
                if (val.StartsWith(RULE_LENGTH + "["))
                {
                    throw new ArgumentException("长度验证格式为：length[1,9]");
                }
                // 范围
                else if (val.StartsWith(RULE_RANGE + "["))
                {
                    throw new ArgumentException("范围验证格式为：range[1,9]");
                }
            }

            string content = val.Substring(startIndex + 1, endIndex - startIndex - 1);

            string[] values = content.Split(',');
            return values;
        }

        private bool IsBetweenLength(string val, string min, string max)
        {
            if (string.IsNullOrEmpty(val))
            {
                return true;
            }

            int intMin = this.ParseInt32(min);
            int intMax = this.ParseInt32(max);
            return val.Length >= intMin && val.Length <= intMax;
        }

        private int ParseInt32(string val)
        {
            try
            {
                return Int32.Parse(val);
            }
            catch (Exception ex)
            {
                throw new Exception(val + ":应该为正整数", ex);
            }
        }

        private bool IsBetweenRange(string val, string min, string max)
        {
            if (string.IsNullOrEmpty(val))
            {
                return true;
            }

            double dblMin = this.ParseDouble(min);
            double dblMax = this.ParseDouble(max);
            double dblValue = this.ParseDouble(val);
            return dblValue >= dblMin && dblValue <= dblMax;
        }

        private double ParseDouble(string val)
        {
            try
            {
                return Double.Parse(val);
            }
            catch (Exception ex)
            {
                throw new Exception(val + ":应该为正浮点数", ex);
            }
        }

        #endregion
    }
}
